////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author or Addison-Wesley Longman make no representations about the
//     suitability of this software for any purpose. It is provided "as is"
//     without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef XGC_SMARTPTR_INC_
#define XGC_SMARTPTR_INC_

#ifdef EXPORT_API
#define EXPORT_LIB __declspec(dllexport)
#else
#define EXPORT_LIB __declspec(dllimport)
#endif
// $Id: SmartPtr.h 1078 2010-09-16 17:32:24Z rich_sposato $


///  \defgroup  SmartPointerGroup Smart pointers
///  Policy based implementation of a smart pointer
///  \defgroup  SmartPointerOwnershipGroup Ownership policies
///  \ingroup   SmartPointerGroup
///  \defgroup  SmartPointerStorageGroup Storage policies
///  \ingroup   SmartPointerGroup
///  \defgroup  SmartPointerConversionGroup Conversion policies
///  \ingroup   SmartPointerGroup
///  \defgroup  SmartPointerCheckingGroup Checking policies
///  \ingroup   SmartPointerGroup

#include <cassert>
#include <string>
#include <functional>
#include <Windows.h>

#include "typemanip.h"
namespace XGC
{
	namespace common
		{

	////////////////////////////////////////////////////////////////////////////////
	///  \class HeapStorage
	///
	///  \ingroup  SmartPointerStorageGroup
	///  Implementation of the StoragePolicy used by SmartPtr.  Uses explicit call
	///   to T's destructor followed by call to free.
	////////////////////////////////////////////////////////////////////////////////


		template <class T>
		class HeapStorage
		{
		public:
			typedef T* StoredType;      /// the type of the pointee_ object
			typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
			typedef T* PointerType;     /// type returned by operator->
			typedef T& ReferenceType;   /// type returned by operator*

		protected:

			HeapStorage() : pointee_(Default())
			{}

			// The storage policy doesn't initialize the stored pointer
			//     which will be initialized by the OwnershipPolicy's Clone fn
			HeapStorage(const HeapStorage&) : pointee_(0)
			{}

			template <class U>
			HeapStorage(const HeapStorage<U>&) : pointee_(0)
			{}

			explicit HeapStorage(const StoredType& p) : pointee_(p) {}

			PointerType operator->() const { return pointee_; }

			ReferenceType operator*() const { return *pointee_; }

			void Swap(HeapStorage& rhs)
			{ std::swap(pointee_, rhs.pointee_); }

			// Accessors
			template <class F>
			friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);

			template <class F>
			friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp);

			template <class F>
			friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp);

			// Destroys the data stored
			// (Destruction might be taken over by the OwnershipPolicy)
			void Destroy()
			{
				if ( 0 != pointee_ )
				{
					pointee_->~T();
					::free( pointee_ );
				}
			}

			// Default value to initialize the pointer
			static StoredType Default()
			{ return 0; }

		private:
			// Data
			StoredType pointee_;
		};

		template <class T>
		inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp)
		{ return sp.pointee_; }


	////////////////////////////////////////////////////////////////////////////////
	///  \class DefaultSPStorage
	///
	///  \ingroup  SmartPointerStorageGroup
	///  Implementation of the StoragePolicy used by SmartPtr
	////////////////////////////////////////////////////////////////////////////////


		template <class T>
		class DefaultSPStorage
		{
		public:
			typedef T* StoredType;    // the type of the pointee_ object
			typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
			typedef T* PointerType;   // type returned by operator->
			typedef T& ReferenceType; // type returned by operator*

		protected:

			DefaultSPStorage() : pointee_(Default())
			{}

			// The storage policy doesn't initialize the stored pointer
			//     which will be initialized by the OwnershipPolicy's Clone fn
			DefaultSPStorage(const DefaultSPStorage&) : pointee_(0)
			{}

			template <class U>
			DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
			{}

			explicit DefaultSPStorage(const StoredType& p) : pointee_(p) {}

			PointerType operator->() const { return pointee_; }

			ReferenceType operator*() const { return *pointee_; }

			void Swap(DefaultSPStorage& rhs)
			{ std::swap(pointee_, rhs.pointee_); }

			// Accessors
			template <class F>
			friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);

			template <class F>
			friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp);

			template <class F>
			friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp);

			// Destroys the data stored
			// (Destruction might be taken over by the OwnershipPolicy)
			//
			// If your compiler gives you a warning in this area while
			// compiling the tests, it is on purpose, please ignore it.
			void Destroy()
			{
				delete pointee_;
			}

			// Default value to initialize the pointer
			static StoredType Default()
			{ return 0; }

		private:
			// Data
			StoredType pointee_;
		};

		template <class T>
		inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp)
		{ return sp.pointee_; }


	////////////////////////////////////////////////////////////////////////////////
	///  \class LockedStorage
	///
	///  \ingroup  SmartPointerStorageGroup
	///  Implementation of the StoragePolicy used by SmartPtr.
	///
	///  Each call to operator-> locks the object for the duration of a call to a
	///  member function of T.
	///
	///  \par How It Works
	///  LockedStorage has a helper class called Locker, which acts as a smart
	///  pointer with limited abilities.  LockedStorage::operator-> returns an
	///  unnamed temporary of type Locker<T> that exists for the duration of the
	///  call to a member function of T.  The unnamed temporary locks the object
	///  when it is constructed by operator-> and unlocks the object when it is
	///  destructed.
	///
	///  \note This storage policy requires class T to have member functions Lock
	///  and Unlock.  If your class does not have Lock or Unlock functions, you may
	///  either make a child class which does, or make a policy class similar to
	///  LockedStorage which calls other functions to lock the object.
	////////////////////////////////////////////////////////////////////////////////

		template <class T>
		class Locker
		{
		public:
			explicit Locker( const T * p ) : pointee_( const_cast< T * >( p ) )
			{
				if ( pointee_ != 0 )
					pointee_->Lock();
			}

			~Locker( void )
			{
				if ( pointee_ != 0 )
					pointee_->Unlock();
			}

			operator T * ()
			{
				return pointee_;
			}

			T * operator->()
			{
				return pointee_;
			}

		private:
			Locker( void );
			Locker & operator = ( const Locker & );
			T * pointee_;
		};

		template <class T>
		class LockedStorage
		{
		public:

			typedef T* StoredType;           /// the type of the pointee_ object
			typedef T* InitPointerType;      /// type used to declare OwnershipPolicy type.
			typedef Locker< T > PointerType; /// type returned by operator->
			typedef T& ReferenceType;        /// type returned by operator*

		protected:

			LockedStorage() : pointee_( Default() ) {}

			~LockedStorage( void ) {}

			LockedStorage( const LockedStorage&) : pointee_( 0 ) {}

			explicit LockedStorage( const StoredType & p ) : pointee_( p ) {}

			PointerType operator->() const
			{
				return Locker< T >( pointee_ );
			}

			void Swap(LockedStorage& rhs)
			{
				std::swap( pointee_, rhs.pointee_ );
			}

			// Accessors
			template <class F>
			friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);

			template <class F>
			friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp);

			template <class F>
			friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp);

			// Destroys the data stored
			// (Destruction might be taken over by the OwnershipPolicy)
			void Destroy()
			{
				delete pointee_;
			}

			// Default value to initialize the pointer
			static StoredType Default()
			{ return 0; }

		private:
			/// Dereference operator is not implemented.
			ReferenceType operator*();

			// Data
			StoredType pointee_;
		};

		template <class T>
		inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
		{ return sp.pointee_; }


	////////////////////////////////////////////////////////////////////////////////
	///  \class ArrayStorage
	///
	///  \ingroup  SmartPointerStorageGroup
	///  Implementation of the ArrayStorage used by SmartPtr
	////////////////////////////////////////////////////////////////////////////////


		template <class T>
		class ArrayStorage
		{
		public:

			typedef T* StoredType;    // the type of the pointee_ object
			typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
			typedef T* PointerType;   // type returned by operator->
			typedef T& ReferenceType; // type returned by operator*

		protected:

			ArrayStorage() : pointee_(Default())
			{}

			// The storage policy doesn't initialize the stored pointer
			//     which will be initialized by the OwnershipPolicy's Clone fn
			ArrayStorage(const ArrayStorage&) : pointee_(0)
			{}

			template <class U>
			ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
			{}

			explicit ArrayStorage(const StoredType& p) : pointee_(p) {}

			PointerType operator->() const { return pointee_; }

			ReferenceType operator*() const { return *pointee_; }

			void Swap(ArrayStorage& rhs)
			{ std::swap(pointee_, rhs.pointee_); }

			// Accessors
			template <class F>
			friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);

			template <class F>
			friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp);

			template <class F>
			friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp);

			// Destroys the data stored
			// (Destruction might be taken over by the OwnershipPolicy)
			void Destroy()
			{ delete [] pointee_; }

			// Default value to initialize the pointer
			static StoredType Default()
			{ return 0; }

		private:
			// Data
			StoredType pointee_;
		};

		template <class T>
		inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp)
		{ return sp.pointee_; }

		template <class T>
		inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp)
		{ return sp.pointee_; }


	////////////////////////////////////////////////////////////////////////////////
	///  \class RefCounted
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Provides a classic external reference counting implementation
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		class RefCounted
		{
		protected:
			RefCounted()
				: pCount_(new uintptr_t)
			{
				assert(pCount_!=0);
				*pCount_ = 1;
			}

			RefCounted(const RefCounted& rhs)
			: pCount_(rhs.pCount_)
			{}

			// MWCW lacks template friends, hence the following kludge
			template <typename P1>
			RefCounted(const RefCounted<P1>& rhs)
			: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
			{}

			P Clone(const P& val)
			{
				++*pCount_;
				return val;
			}

			bool Release(const P&)
			{
				if (!--*pCount_)
				{
					delete pCount_;
					pCount_ = NULL;
					return true;
				}
				return false;
			}

			void Swap(RefCounted& rhs)
			{ std::swap(pCount_, rhs.pCount_); }

			enum { destructiveCopy = false };

		private:
			// Data
			uintptr_t* pCount_;
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct RefCountedMT
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Implements external reference counting for multithreaded programs
	///  Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
	///
	///  \par Warning
	///  There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release"
	///  http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644
	///  As stated in bug 1408845, the Release function is not thread safe if a
	///  SmartPtr copy-constructor tries to copy the last pointer to an object in
	///  one thread, while the destructor is acting on the last pointer in another
	///  thread.  The existence of a race between a copy-constructor and destructor
	///  implies a design flaw at a higher level.  That race condition must be
	///  fixed at a higher design level, and no change to this class could fix it.
	////////////////////////////////////////////////////////////////////////////////

		template< class P >
		class RefCountedMT
		{
		protected:
			RefCountedMT()
				: pCount_ (new volatile uintptr_t)
			{
				assert(pCount_);
				*pCount_ = 1;
			}

			RefCountedMT(const RefCountedMT& rhs)
			: pCount_(rhs.pCount_)
			{}

			//MWCW lacks template friends, hence the following kludge
			template <typename P1>
			RefCountedMT(const RefCountedMT<P1>& rhs)
			: pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
			{}

			P Clone(const P& val)
			{
				InterlockedIncrement(reinterpret_cast< volatile long* >(pCount_));
				return val;
			}

			bool Release(const P&)
			{
				volatile long ref = InterlockedDecrement(reinterpret_cast< volatile long* >(pCount_));
				if ( !ref )
				{
					delete const_cast<uintptr_t*>(pCount_);
					pCount_ = 0;
					return true;
				}
				return false;
			}

			void Swap(RefCountedMT& rhs)
			{ std::swap(pCount_, rhs.pCount_); }

			enum { destructiveCopy = false };

		private:
			// Data
			volatile uintptr_t* pCount_;
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \class COMRefCounted
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		class COMRefCounted
		{
		protected:
			COMRefCounted()
			{}

			template <class U>
			COMRefCounted(const COMRefCounted<U>&)
			{}

			static P Clone(const P& val)
			{
				if(val!=0)
				   val->AddRef();
				return val;
			}

			static bool Release(const P& val)
			{
				if(val!=0)
					val->Release();
				return false;
			}

			enum { destructiveCopy = false };

			static void Swap(COMRefCounted&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct DeepCopy
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Implements deep copy semantics, assumes existence of a Clone() member
	///  function of the pointee type
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct DeepCopy
		{
		protected:
			DeepCopy()
			{}

			template <class P1>
			DeepCopy(const DeepCopy<P1>&)
			{}

			static P Clone(const P& val)
			{ return val->Clone(); }

			static bool Release(const P&)
			{ return true; }

			static void Swap(DeepCopy&)
			{}

			enum { destructiveCopy = false };
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \class RefLinked
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Implements reference linking
	////////////////////////////////////////////////////////////////////////////////

		namespace Private
		{
			class /*EXPORT_LIB*/ RefLinkedBase
			{
			protected:
				RefLinkedBase( void )
				{
					prev_ = next_ = this;
				}

				RefLinkedBase(const RefLinkedBase& rhs);

				bool Release();

				void Swap(RefLinkedBase& rhs);

				bool Merge( RefLinkedBase & rhs );

				enum { destructiveCopy = false };

			private:
				static unsigned int CountPrevCycle( const RefLinkedBase * pThis );
				static unsigned int CountNextCycle( const RefLinkedBase * pThis );
				bool HasPrevNode( const RefLinkedBase * p ) const;
				bool HasNextNode( const RefLinkedBase * p ) const;

				mutable const RefLinkedBase* prev_;
				mutable const RefLinkedBase* next_;
			};
		}

		template <class P>
		class RefLinked : public Private::RefLinkedBase
		{
		protected:
			RefLinked()
			{}

			template <class P1>
			RefLinked(const RefLinked<P1>& rhs)
			: Private::RefLinkedBase(rhs)
			{}

			static P Clone(const P& val)
			{ return val; }

			bool Release(const P&)
			{ return Private::RefLinkedBase::Release(); }

			template < class P1 >
			bool Merge( RefLinked< P1 > & rhs )
			{
				return Private::RefLinkedBase::Merge( rhs );
			}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \class DestructiveCopy
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Implements destructive copy semantics (a la std::auto_ptr)
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		class DestructiveCopy
		{
		protected:
			DestructiveCopy()
			{}

			template <class P1>
			DestructiveCopy(const DestructiveCopy<P1>&)
			{}

			template <class P1>
			static P Clone(P1& val)
			{
				P result(val);
				val = P1();
				return result;
			}

			static bool Release(const P&)
			{ return true; }

			static void Swap(DestructiveCopy&)
			{}

			enum { destructiveCopy = true };
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \class NoCopy
	///
	///  \ingroup  SmartPointerOwnershipGroup
	///  Implementation of the OwnershipPolicy used by SmartPtr
	///  Implements a policy that doesn't allow copying objects
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		class NoCopy
		{
		protected:
			NoCopy()
			{}

			template <class P1>
			NoCopy(const NoCopy<P1>&)
			{}

			static P Clone(const P&)
			{
				// Make it depended on template parameter
				static const bool DependedFalse = sizeof(P*) == 0;

				// LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
			}

			static bool Release(const P&)
			{ return true; }

			static void Swap(NoCopy&)
			{}

			enum { destructiveCopy = false };
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct AllowConversion
	///
	///  \ingroup  SmartPointerConversionGroup
	///  Implementation of the ConversionPolicy used by SmartPtr
	///  Allows implicit conversion from SmartPtr to the pointee type
	////////////////////////////////////////////////////////////////////////////////

		struct AllowConversion
		{
			enum { allow = true };

			void Swap(AllowConversion&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct DisallowConversion
	///
	///  \ingroup  SmartPointerConversionGroup
	///  Implementation of the ConversionPolicy used by SmartPtr
	///  Does not allow implicit conversion from SmartPtr to the pointee type
	///  You can initialize a DisallowConversion with an AllowConversion
	////////////////////////////////////////////////////////////////////////////////

		struct DisallowConversion
		{
			DisallowConversion()
			{}

			DisallowConversion(const AllowConversion&)
			{}

			enum { allow = false };

			void Swap(DisallowConversion&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct NoCheck
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Well, it's clear what it does :o)
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct NoCheck
		{
		protected:

			NoCheck()
			{}

			template <class P1>
			NoCheck(const NoCheck<P1>&)
			{}

			static void OnDefault(const P&)
			{}

			static void OnInit(const P&)
			{}

			static void OnDereference(const P&)
			{}

			static void Swap(NoCheck&)
			{}
		};


	////////////////////////////////////////////////////////////////////////////////
	///  \struct AssertCheck
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Checks the pointer before dereference
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct AssertCheck
		{
		protected:

			AssertCheck()
			{}

			template <class P1>
			AssertCheck(const AssertCheck<P1>&)
			{}

			template <class P1>
			AssertCheck(const NoCheck<P1>&)
			{}

			static void OnDefault(const P&)
			{}

			static void OnInit(const P&)
			{}

			static void OnDereference(P val)
			{ assert(val); (void)val; }

			static void Swap(AssertCheck&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct AssertCheckStrict
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Checks the pointer against zero upon initialization and before dereference
	///  You can initialize an AssertCheckStrict with an AssertCheck
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct AssertCheckStrict
		{
		protected:

			AssertCheckStrict()
			{}

			template <class U>
			AssertCheckStrict(const AssertCheckStrict<U>&)
			{}

			template <class U>
			AssertCheckStrict(const AssertCheck<U>&)
			{}

			template <class P1>
			AssertCheckStrict(const NoCheck<P1>&)
			{}

			static void OnDefault(P val)
			{ assert(val); }

			static void OnInit(P val)
			{ assert(val); }

			static void OnDereference(P val)
			{ assert(val); }

			static void Swap(AssertCheckStrict&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct NullPointerException
	///
	///  \ingroup SmartPointerGroup
	///  Used by some implementations of the CheckingPolicy used by SmartPtr
	////////////////////////////////////////////////////////////////////////////////

		struct NullPointerException : public std::runtime_error
		{
			NullPointerException() : std::runtime_error(std::string(""))
			{ }
			const char* what() const throw()
			{ return "Null Pointer Exception"; }
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct RejectNullStatic
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Checks the pointer upon initialization and before dereference
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct RejectNullStatic
		{
		protected:

			RejectNullStatic()
			{}

			template <class P1>
			RejectNullStatic(const RejectNullStatic<P1>&)
			{}

			template <class P1>
			RejectNullStatic(const NoCheck<P1>&)
			{}

			template <class P1>
			RejectNullStatic(const AssertCheck<P1>&)
			{}

			template <class P1>
			RejectNullStatic(const AssertCheckStrict<P1>&)
			{}

			static void OnDefault(const P&)
			{
				// Make it depended on template parameter
				static const bool DependedFalse = sizeof(P*) == 0;

				// LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
			}

			static void OnInit(const P& val)
			{ if (!val) throw NullPointerException(); }

			static void OnDereference(const P& val)
			{ if (!val) throw NullPointerException(); }

			static void Swap(RejectNullStatic&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct RejectNull
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Checks the pointer before dereference
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct RejectNull
		{
		protected:

			RejectNull()
			{}

			template <class P1>
			RejectNull(const RejectNull<P1>&)
			{}

			static void OnInit(P)
			{}

			static void OnDefault(P)
			{}

			void OnDereference(P val)
			{ if (!val) throw NullPointerException(); }

			void OnDereference(P val) const
			{ if (!val) throw NullPointerException(); }

			void Swap(RejectNull&)
			{}
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \struct RejectNullStrict
	///
	///  \ingroup  SmartPointerCheckingGroup
	///  Implementation of the CheckingPolicy used by SmartPtr
	///  Checks the pointer upon initialization and before dereference
	////////////////////////////////////////////////////////////////////////////////

		template <class P>
		struct RejectNullStrict
		{
		protected:

			RejectNullStrict()
			{}

			template <class P1>
			RejectNullStrict(const RejectNullStrict<P1>&)
			{}

			template <class P1>
			RejectNullStrict(const RejectNull<P1>&)
			{}

			static void OnInit(P val)
			{ if (!val) throw NullPointerException(); }

			void OnDereference(P val)
			{ OnInit(val); }

			void OnDereference(P val) const
			{ OnInit(val); }

			void Swap(RejectNullStrict&)
			{}
		};

		template <class T>
		class RefToValue
		{   
		public:

			RefToValue(T& ref) : ref_(ref) 
			{}

			RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
			{}

			operator T& () const 
			{
				return ref_;
			}

		private:
			// Disable - not implemented
			RefToValue();
			RefToValue& operator=(const RefToValue&);

			T& ref_;
		};


		////////////////////////////////////////////////////////////////////////////////
		///  \ingroup ExceptionGroup 
		///  RefToValue creator.
		////////////////////////////////////////////////////////////////////////////////

		template <class T>
		inline RefToValue<T> ByRef(T& t)
		{
			return RefToValue<T>(t);
		}    

	////////////////////////////////////////////////////////////////////////////////
	// class template SmartPtr (declaration)
	// The reason for all the fuss above
	////////////////////////////////////////////////////////////////////////////////
	#if defined(_MT)
		#define RefCountedDefault RefCountedMT
	#else
		#define RefCountedDefault RefCounted
	#endif

		template
		<
			typename T,
			template <class> class OwnershipPolicy = RefCountedDefault,
			class ConversionPolicy = DisallowConversion,
			template <class> class CheckingPolicy = AssertCheck,
			template <class> class StoragePolicy = DefaultSPStorage
		 >
		 class SmartPtr;

	////////////////////////////////////////////////////////////////////////////////
	// class template SmartPtrDef (definition)
	// this class added to unify the usage of SmartPtr
	// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OwnershipPolicy = RefCountedDefault,
			class ConversionPolicy = DisallowConversion,
			template <class> class CheckingPolicy = AssertCheck,
			template <class> class StoragePolicy = DefaultSPStorage
		>
		struct SmartPtrDef
		{
			typedef SmartPtr
			<
				T,
				OwnershipPolicy,
				ConversionPolicy,
				CheckingPolicy,
				StoragePolicy
			>
			type;
		};

	////////////////////////////////////////////////////////////////////////////////
	///  \class SmartPtr
	///
	///  \ingroup SmartPointerGroup
	///
	///  \param OwnershipPolicy  default =  RefCounted,
	///  \param ConversionPolicy default = DisallowConversion,
	///  \param CheckingPolicy default = AssertCheck,
	///  \param StoragePolicy default = DefaultSPStorage
	///  \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
	///
	///  \par IMPORTANT NOTE
	///  Due to threading issues, the OwnershipPolicy has been changed as follows:
	///
	///     - Release() returns a boolean saying if that was the last release
	///        so the pointer can be deleted by the StoragePolicy
	///     - IsUnique() was removed
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OwnershipPolicy,
			class ConversionPolicy,
			template <class> class CheckingPolicy,
			template <class> class StoragePolicy
		>
		class SmartPtr
			: public StoragePolicy<T>
			, public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
			, public CheckingPolicy<typename StoragePolicy<T>::StoredType>
			, public ConversionPolicy
		{
			typedef StoragePolicy<T> SP;
			typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
			typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
			typedef ConversionPolicy CP;

		public:
			typedef typename const T* ConstPointerType;
			typedef typename const T& ConstReferenceType;

			typedef typename SP::PointerType PointerType;
			typedef typename SP::StoredType StoredType;
			typedef typename SP::ReferenceType ReferenceType;

			typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
					CopyArg;

		private:
			struct NeverMatched {};

	#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
			typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
			typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
	#else
			typedef const StoredType& ImplicitArg;
			typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
	#endif

			/// SmartPtr uses this helper class to specify the dynamic-caster constructor.
			class DynamicCastHelper {};

			/// Private constructor is only used for dynamic-casting.
			template
			<
				typename T1,
				template < class > class OP1,
				class CP1,
				template < class > class KP1,
				template < class > class SP1
			>
			SmartPtr( const SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs, const DynamicCastHelper & helper )
			{
				(void)helper; // do void cast to remove compiler warning.
				// Dynamic casting from T1 to T and saving result in `this''s pointer
				PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
				GetImplRef( *this ) = OP::Clone( p );
			}

			/// Private constructor is only used for dynamic-casting.
			template
			<
				typename T1,
				template < class > class OP1,
				class CP1,
				template < class > class KP1,
				template < class > class SP1
			>
			SmartPtr( SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs, const DynamicCastHelper & helper )
			{
				(void)helper; // do void cast to remove compiler warning.
				// Dynamic casting from T1 to T and saving result in `this''s pointer
				PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
				GetImplRef( *this ) = OP::Clone( p );
			}

		public:

			SmartPtr()
			{
				KP::OnDefault(GetImpl(*this));
			}

			explicit
			SmartPtr(ExplicitArg p) : SP(p)
			{
				KP::OnInit(GetImpl(*this));
			}

			SmartPtr(ImplicitArg p) : SP(p)
			{
				KP::OnInit(GetImpl(*this));
			}

			SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
			{
				GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
			}

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs)
			: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
			{
				GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
			}

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs)
			: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
			{
				GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
			}

			SmartPtr(RefToValue<SmartPtr> rhs)
			: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
			{}

			operator RefToValue<SmartPtr>()
			{ return RefToValue<SmartPtr>(*this); }

			SmartPtr& operator=(CopyArg& rhs)
			{
				SmartPtr temp(rhs);
				temp.Swap(*this);
				return *this;
			}

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs)
			{
				SmartPtr temp(rhs);
				temp.Swap(*this);
				return *this;
			}

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs)
			{
				SmartPtr temp(rhs);
				temp.Swap(*this);
				return *this;
			}

			void Swap(SmartPtr& rhs)
			{
				OP::Swap(rhs);
				CP::Swap(rhs);
				KP::Swap(rhs);
				SP::Swap(rhs);
			}

			~SmartPtr()
			{
				if (OP::Release(GetImpl(*static_cast<SP*>(this))))
				{
					SP::Destroy();
				}
			}

			/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
			template
			<
				typename T1,
				template < class > class OP1,
				class CP1,
				template < class > class KP1,
				template < class > class SP1
			>
			SmartPtr & DynamicCastFrom( const SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				SmartPtr temp( rhs, DynamicCastHelper() );
				temp.Swap( *this );
				return *this;
			}

			/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
			template
			<
				typename T1,
				template < class > class OP1,
				class CP1,
				template < class > class KP1,
				template < class > class SP1
			>
			SmartPtr & DynamicCastFrom( SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				SmartPtr temp( rhs, DynamicCastHelper() );
				temp.Swap( *this );
				return *this;
			}

	#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND

			// old non standard in class definition of friends
			friend inline void Release(SmartPtr& sp, typename SP::StoredType& p)
			{
				p = GetImplRef(sp);
				GetImplRef(sp) = SP::Default();
			}

			friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
			{ SmartPtr(p).Swap(sp); }

	#else

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
	            
			>
			friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1>& sp,
								typename SP1<T1>::StoredType& p);

			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
	            
			>
			friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1>& sp,
							  typename SP1<T1>::StoredType p);
	#endif


			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				if ( GetImpl( *this ) != GetImpl( rhs ) )
				{
					return false;
				}
				return OP::template Merge( rhs );
			}

			PointerType operator->()
			{
				KP::OnDereference(GetImplRef(*this));
				return SP::operator->();
			}

			ConstPointerType operator->() const
			{
				KP::OnDereference(GetImplRef(*this));
				return SP::operator->();
			}

			ReferenceType operator*()
			{
				KP::OnDereference(GetImplRef(*this));
				return SP::operator*();
			}

			ConstReferenceType operator*() const
			{
				KP::OnDereference(GetImplRef(*this));
				return SP::operator*();
			}

			bool operator!() const // Enables "if (!sp) ..."
			{ return GetImpl(*this) == 0; }

			static inline T * GetPointer( const SmartPtr & sp )
			{ return GetImpl( sp ); }

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs) const
			{ return GetImpl(*this) == GetImpl(rhs); }

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs) const
			{ return !(*this == rhs); }

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1 >& rhs) const
			{ return GetImpl(*this) < GetImpl(rhs); }

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				return ( GetImpl( rhs ) < GetImpl( *this ) );
			}

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				return !( GetImpl( rhs ) < GetImpl( *this ) );
			}

			// Ambiguity buster
			template
			<
				typename T1,
				template <class> class OP1,
				class CP1,
				template <class> class KP1,
				template <class> class SP1
			>
			inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1 > & rhs )
			{
				return !( GetImpl( *this ) < GetImpl( rhs ) );
			}

		private:
			// Helper for enabling 'if (sp)'
			struct Tester
			{
				Tester(int) {}
				void dummy() {}
			};

			typedef void (Tester::*unspecified_boolean_type_)();

			typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
				unspecified_boolean_type;

		public:
			// enable 'if (sp)'
			operator unspecified_boolean_type() const
			{
				return !*this ? 0 : &Tester::dummy;
			}

		private:
			// Helper for disallowing automatic conversion
			struct Insipid
			{
				Insipid(PointerType) {}
			};

			typedef typename Select<CP::allow, PointerType, Insipid>::Result
				AutomaticConversionResult;

		public:
			operator AutomaticConversionResult() const
			{ return GetImpl(*this); }
		};


	////////////////////////////////////////////////////////////////////////////////
	// friends
	////////////////////////////////////////////////////////////////////////////////

	#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP
		>
		inline void Release(SmartPtr<T, OP, CP, KP, SP>& sp,
							typename SP<T>::StoredType& p)
		{
		  p = GetImplRef(sp);
		  GetImplRef(sp) = SP<T>::Default();
		}

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP
		>
		inline void Reset(SmartPtr<T, OP, CP, KP, SP>& sp,
						  typename SP<T>::StoredType p)
		{ SmartPtr<T, OP, CP, KP, SP>(p).Swap(sp); }

	#endif

	////////////////////////////////////////////////////////////////////////////////
	// free comparison operators for class template SmartPtr
	////////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////////
	///  operator== for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator==(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{ return ( GetImpl( lhs ) == rhs ); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator== for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator==(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{ return ( GetImpl( rhs ) == lhs ); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator!= for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{ return ( GetImpl( lhs ) != rhs ); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator!= for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator!=(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{ return ( GetImpl( rhs ) != lhs ); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator< for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator<(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{
			return ( GetImpl( lhs ) < rhs );
		}

	////////////////////////////////////////////////////////////////////////////////
	///  operator< for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator<(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{
			return ( lhs < GetImpl( rhs ) );
		}

	////////////////////////////////////////////////////////////////////////////////
	//  operator> for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator>(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{ return rhs < GetImpl( lhs ); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator> for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator>(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{ return rhs < lhs; }

	////////////////////////////////////////////////////////////////////////////////
	///  operator<= for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{ return !(rhs < lhs); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator<= for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator<=(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{ return !(rhs < lhs); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator>= for lhs = SmartPtr, rhs = raw pointer
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP >& lhs,
			U* rhs)
		{ return !(lhs < rhs); }

	////////////////////////////////////////////////////////////////////////////////
	///  operator>= for lhs = raw pointer, rhs = SmartPtr
	///  \ingroup SmartPointerGroup
	////////////////////////////////////////////////////////////////////////////////

		template
		<
			typename T,
			template <class> class OP,
			class CP,
			template <class> class KP,
			template <class> class SP,
			typename U
		>
		inline bool operator>=(U* lhs,
			const SmartPtr<T, OP, CP, KP, SP >& rhs)
		{ return !(lhs < rhs); }

	}; // namespace common
};
////////////////////////////////////////////////////////////////////////////////
///  specialization of std::less for SmartPtr
///  \ingroup SmartPointerGroup
////////////////////////////////////////////////////////////////////////////////

namespace std
{
    template
    <
        typename T,
        template <class> class OP,
        class CP,
        template <class> class KP,
        template <class> class SP 
	>
	struct less< XGC::common::SmartPtr<T, OP, CP, KP, SP> >
        : public binary_function<XGC::common::SmartPtr<T, OP, CP, KP, SP >, XGC::common::SmartPtr<T, OP, CP, KP, SP >, bool>
    {
        bool operator()(const XGC::common::SmartPtr<T, OP, CP, KP, SP >& lhs,
            const XGC::common::SmartPtr<T, OP, CP, KP, SP >& rhs) const
        { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
    };
}

// ----------------------------------------------------------------------------
#endif // end file guardian
